﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using System.ComponentModel;
using System.Reflection;

namespace DS2171Utils
{
    // preleva membri e proprietà degli oggetti
    public class DynamicBindingProxy : DynamicObject, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private static readonly Dictionary<string, Dictionary<string, PropertyInfo>> cacheClassi =
            new Dictionary<string, Dictionary<string, PropertyInfo>>();
        //private readonly T instance;   
        private Type  m_Instance; 
        private string typeName;

        public DynamicBindingProxy(Type pInstance)
        {
            m_Instance = pInstance;
            var type = pInstance;// typeof(T);
            typeName = type.FullName;
            if (!cacheClassi.ContainsKey(typeName))
                SetProperties(type, typeName);
        }

        public DynamicBindingProxy()
        {

        }

        public void PrelevaMappaOggetto(Type pInstance)
        {
            m_Instance = pInstance;
            var type = pInstance;// typeof(T);
            typeName = type.FullName;
            if (!cacheClassi.ContainsKey(typeName))
                SetProperties(type, typeName);
        }

        public Dictionary<string, PropertyInfo> getMembriTypo(string pFullNameTipo)
        {
            return cacheClassi[pFullNameTipo];
        }//fM

        private static void SetProperties(Type type, string typeName)
        {
            var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var dict = props.ToDictionary(prop => prop.Name);
            cacheClassi.Add(typeName, dict);
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (cacheClassi[typeName].ContainsKey(binder.Name))
            {
                result = cacheClassi[typeName][binder.Name].GetValue(m_Instance, null);
                return true;
            }
            result = null;
            return false;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (cacheClassi[typeName].ContainsKey(binder.Name))
            {
                cacheClassi[typeName][binder.Name].SetValue(m_Instance, value, null);
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(binder.Name));
                return true;
            }
            return false;
        }
    }//fC

}
